import * as THREE from 'three'
import Experience from '../class/Experience';
import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
import lineData from '../data/line'
// 引入线宽设置相关库
import { LineSegmentsGeometry } from 'three/examples/jsm/lines/LineSegmentsGeometry.js';
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry.js';
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js';
import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2.js';
import { Line2 } from 'three/examples/jsm/lines/Line2.js';
import Utils from '../class/Utils';

class LineGroup {
    constructor() {
        this.experience = new Experience();
        this.lineGroup = new THREE.Group()
        this.flyLineGroup = new THREE.Group();
        this.lineGroup.position.y = 1;
        this.flyLineGroup.position.y = 4;
        this.createLineGroup();
        this.createFlyLine();
    }
    createLineGroup() {
        this.lineArr = []
        lineData.forEach((item, index) => {
            const obj = new SingleLine([...item.position]);
            this.lineGroup.add(obj.line);
            // this.lineArr.push(obj.line)
        });
    }
    createFlyLine() {
        this.lineGroup.children.forEach(item => {
            // const dividerNumber = Math.floor(item.points.length / 5)

            // for (let i = 1; i <= 5; i++) {
            //     const obj = new Flyline2(item.points, i * dividerNumber)
            //     this.flyLineGroup.add(obj.flyLine);
            // }
            const obj = new Flyline2(item.points)
            // const obj = new Flyline(item.points)
            // console.log(obj);
            this.flyLineGroup.add(obj.flyLine);
        })
    }

    // 飞线更新
    update() {
        this.flyLineGroup.children.forEach(item => {
            // console.log(item);
            if (item.index > item.indexMax) item.index = 0;
            item.index += 1;
            const newPoints = item.points.slice(item.index, item.index + item.number);
            const curve = new THREE.CatmullRomCurve3(newPoints, false, "catmullrom", 0);
            const newPoints2 = curve.getSpacedPoints(item.dividerNumber); //获取更多的点数
            item.geometry.setFromPoints(newPoints2);
        })
    }

    // Line2类型的飞线更新
    updateLine2() {
        this.flyLineGroup.children.forEach(item => {
            // console.log(item);
            if (item.index > item.indexMax) item.index = 0;
            item.index += 1;
            const newPoints = item.points.slice(item.index, item.index + item.number)
            const newPoints2 = Utils.vector3ArrToNormal(newPoints);
            item.geometry.setPositions(newPoints2);
        })
    }
}

// 创建线条
class SingleLine {
    points = [];
    pointNumber = 100;
    color = 0xEC384C;
    linewidth = 2;
    lineLong = 0;
    constructor(pointArr = []) {
        this.experience = new Experience();
        const sizes = this.experience.sizes;
        // this.lineLong = this.getLineLong(pointArr);
        // this.pointNumber = parseInt(this.lineLong / 3)

        const geometry = new LineGeometry(); //创建一个缓冲类型几何体
        const lineArr = Utils.pointArrToVector3(pointArr);
        const curve = new THREE.CatmullRomCurve3([
            ...lineArr
        ], false, 'catmullrom', 0);
        const points = curve.getPoints(this.pointNumber); //分段数100，返回101个顶点
        const lineList = Utils.vector3ArrToNormal(points)
        geometry.setPositions(lineList);
        const material = new LineMaterial({
            linewidth: this.linewidth,
            color: this.color, //轨迹颜色
            // transparent: true,
            // opacity: 0.4
        });
        material.resolution.set(sizes.width, sizes.height);
        this.line = new Line2(geometry, material);
        this.line.points = points;
        // this.line.pointNumber = this.pointNumber;
        // this.line.color = this.color;
        // this.line.linewidth = this.linewidth;
        // console.log();

    }
    getLineLong(pointArr) {
        let d = 0;
        for (let i = 0; i < pointArr.length - 1; i++) {
            d += this.distance(pointArr[i], pointArr[i + 1])
        }
        return d
    }
    // 平面坐标系两点距离
    distance(pre, next) {
        const dX = Math.abs(next[0] - pre[0])
        const dY = Math.abs(next[1] - pre[1])
        const dis = dX * dX + dY * dY
        return Math.sqrt(dis)
    }
}

// 创建飞线
class Flyline {
    // 飞线基于线段点位起始位置
    index = 0;
    // 飞线终点
    indexMax = 0;
    // 飞线取线段点位数量
    number = 15;
    // 飞线自身点数
    dividerNumber = 100;
    // 飞线父级线条的点位数组
    // points = []

    size = 15

    constructor(points = []) {
        this.points = points;
        // this.number = parseInt( points.length / 20 )
        // 用于循环渲染所有飞线
        // 每条飞线最多能跑的点数 超过归零循环
        this.indexMax = this.points.length - this.number
        const list = points.slice(this.index, this.index + this.number);
        const curve = new THREE.CatmullRomCurve3(list, false, 'catmullrom', 0);
        const points2 = curve.getPoints(this.dividerNumber);
        const geometry = new THREE.BufferGeometry();
        geometry.setFromPoints(points2);

        const percentArr = []; //attributes.percent的数据
        for (let i = 0; i < points2.length; i++) {
            percentArr.push(i / points2.length);
        }

        const percentAttribue = new THREE.BufferAttribute(new Float32Array(percentArr), 1);
        geometry.attributes.percent = percentAttribue;


        // 批量计算所有顶点颜色数据
        const colorArr = [];
        for (let i = 0; i < points2.length; i++) {
            let color1 = new THREE.Color(0xff2000); //轨迹线颜色 青色
            let color2 = new THREE.Color(0xffff00); //黄色
            let color = color1.lerp(color2, i / points2.length)
            colorArr.push(color.r, color.g, color.b);
        }

        // 设置几何体顶点颜色数据
        geometry.attributes.color = new THREE.BufferAttribute(new Float32Array(colorArr), 3);


        // 点模型渲染几何体每个顶点
        const PointsMaterial = new THREE.PointsMaterial({
            // color: 0xffff00,
            size: this.size, //点大小
            vertexColors: true, //使用顶点颜色渲染
        });

        PointsMaterial.onBeforeCompile = (shader) => {
            // 顶点着色器中声明一个attribute变量:百分比
            shader.vertexShader = shader.vertexShader.replace(
                'void main() {',
                [
                    'attribute float percent;', //顶点大小百分比变量，控制点渲染大小
                    'void main() {',
                ].join('\n') // .join()把数组元素合成字符串
            );
            // 调整点渲染大小计算方式
            shader.vertexShader = shader.vertexShader.replace(
                'gl_PointSize = size;',
                [
                    'gl_PointSize = percent * size;',
                ].join('\n') // .join()把数组元素合成字符串
            );
        };


        const flyLine = new THREE.Points(geometry, PointsMaterial);
        this.flyLine = flyLine;
        this.flyLine.points = points;
        this.flyLine.index = this.index;
        this.flyLine.indexMax = this.indexMax;
        this.flyLine.number = this.number;
        this.flyLine.dividerNumber = this.dividerNumber;
    }


}

// 创建Line2飞线
class Flyline2 {
    index = 0;

    number = 2;

    linewidth = 4;

    color = 0xffff00

    constructor(points = []) {
        // this.index = start;
        this.experience = new Experience();
        const sizes = this.experience.sizes;
        const list = points.slice(this.index, this.index + this.number);
        const geometry = new LineGeometry();
        const arr = Utils.vector3ArrToNormal(list);
        geometry.setPositions(arr);
        const material = new LineMaterial({
            color: this.color, //设置线条颜色值
            linewidth: this.linewidth, // 设置线宽            
            // vertexColors: THREE.VertexColors, // 注释color设置，启用顶点颜色渲染
        });
        material.resolution.set(sizes.width, sizes.height);
        const line = new Line2(geometry, material)
        // 记录初始化时的数据 飞线运动时在初始化数据上增减
        line.points = points
        line.index = this.index
        line.indexMax = points.length - this.number
        line.number = this.number
        this.flyLine = line
    }
}

export {
    LineGroup
}